//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <winhack.h>
#include <elasysapi.h>
#include "hacker.h"
#include "mouse.h"
#include "keyboard.h"
#include "ime.h"
#include "video.h"
#include "notifiercenter.h"
#include <aura.h>
#include "stdlib.h"

extern void GetWndInfoFromConfigXml(
        /* [out] */ Int32 * pPosX,
        /* [out] */ Int32 * pPosY,
        /* [out] */ Int32 * pWidth,
        /* [out] */ Int32 * pHeight
        );

void GetWindowInfomation(
        /* [out] */ Int32 * pPosX,
        /* [out] */ Int32 * pPosY,
        /* [out] */ Int32 * pWidth,
        /* [out] */ Int32 * pHeight)
{
   // wchar_t * cmdLine = (wchar_t *)AuraProcess_GetCommandLine();

    wchar_t imageName[64];
    wchar_t cmdLine[260];
#if _DEBUG
    ECode ec =
#endif
    AuraProcess_GetStartInfo(imageName, cmdLine);
#if _DEBUG
    assert(SUCCEEDED(ec));
#endif
    wchar_t * pCur = cmdLine;
    Int32 temp;

    for (; (*pCur < L'0') || (*pCur > L'9'); pCur++);
    for (temp = 0;
         (*pCur >= L'0') && (*pCur <= L'9');
         pCur++) {
        temp = temp * 10 + *pCur - L'0';
    }
    *pPosX = temp;

    for (; *pCur == L' '; pCur++);
    for (temp = 0;
         (*pCur >= L'0') && (*pCur <= L'9');
         pCur++) {
        temp = temp * 10 + *pCur - L'0';
    }
    *pPosY = temp;

    for (; *pCur == L' '; pCur++);
    for (temp = 0;
         (*pCur >= L'0') && (*pCur <= L'9');
         pCur++) {
        temp = temp * 10 + *pCur - L'0';
    }
    *pWidth = (temp <= 0) ? 240 : temp;

    for (; *pCur == L' '; pCur++);
    for (temp = 0;
         (*pCur >= L'0') && (*pCur <= L'9');
         pCur++) {
        temp = temp * 10 + *pCur - L'0';
    }
    *pHeight = (temp <= 0) ? 320 : temp;

    return ;
}

ECode CHacker::Read(
    /* [in] */ Int64 offset,
    /* [in] */ Int32 numberOfBytesToRead,
    /* [out] */ MemoryBuf * pData,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    // TODO;
    return E_NOT_IMPLEMENTED;
}

ECode CHacker::Write(
    /* [in] */ Int64 offset,
    /* [in] */ const MemoryBuf & ebbData,
    /* [out] */ Int32 * pNumberOfBytesWritten,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    // TODO;
    return E_NOT_IMPLEMENTED;
}

ECode CHacker::Control(
    /* [in] */ Handle32 controlCode,
    /* [in] */ const MemoryBuf & ebbInData,
    /* [out] */ MemoryBuf * pOutData,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    Int32 type = controlCode & 0xffff;
  //  Int32 code = controlCode >> 16;
    Int32 environmentId = *(Int32*)ebbInData.GetPayload();
    ECode ec = NOERROR;
    IDeviceDriver * pDriver = NULL;

    if ((NULL == pOutData)
        || (pOutData->GetCapacity() < (Int32)sizeof(Address))) {
        return E_INVALID_ARGUMENT;
    }

    switch (type) {
    case DRIVER_KEYBOARD:
    case DRIVER_MOUSE:
    case DRIVER_VIDEO:
    case DRIVER_NOTIFIERCENTER:
    case DRIVER_IME:
        ec = GetSpecialDriver(type, environmentId, &pDriver);
        break;
    default:
        assert(0);
        break;
    }
    *(Address *)pOutData->GetPayload() = (Address)pDriver;
    return ec;
}

void CHacker::Dispose()
{
   // do nothing.
   return ;
}

ECode CHacker::GetSpecialDriver(
        /* [in] */ Int32 driverType,
        /* [in] */ Int32 environmentId,
        /* [out] */ IDeviceDriver ** ppDriver)
{
    IDeviceDriver * pDriver = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppDriver);

    switch(driverType) {
    case DRIVER_KEYBOARD:
        ec = CKeyboard::S_Create(environmentId, ppDriver);
        break;

    case DRIVER_MOUSE:
        ec = CMouse::S_Create(environmentId, ppDriver);
        break;

    case DRIVER_VIDEO: {
        Int32 posX   = 100;
        Int32 posY   = 100;
        Int32 width  = 300;
        Int32 height = 800 ;

        GetWndInfoFromConfigXml(&posX, &posY, &width, &height);
        //TODO:becuase we  doesn't support rgb888 color fomart
        Int32 colorFomart=COLOR_RGB565;
        //not use _wgetenv,because here it's function of elastos
        char* colorEnv=getenv("XDK_TARGET_PRODUCT");
        if(colorEnv && (0 == _stricmp(colorEnv,"c28")))
        {
             colorFomart=COLOR_RGBT666;
        }
        pDriver = new CVideo(posX, posY, width, height, environmentId,colorFomart);
        if (NULL == pDriver) {
            ec = E_OUT_OF_MEMORY;
            break;
        }
        ec = ((CVideo *)pDriver)->Initialize();
        if (FAILED(ec)) {
            delete pDriver;
            pDriver = NULL;
            break;
        }
        break;
    }
    case DRIVER_NOTIFIERCENTER: {
        extern CNotifierCenter g_notifierCenter;
        *ppDriver = (IDeviceDriver *)&g_notifierCenter;
        break;
    }
    case DRIVER_IME: {
        ec = CIME::S_Create(environmentId, ppDriver);
        break;
    }
    default:
        assert(0);
        break;
    }

    if (NULL != pDriver) {
        assert(SUCCEEDED(ec));
        pDriver->AddRef();
        *ppDriver = pDriver;
    }
    return ec;
}

ECode GetHackHelper(IDeviceDriver ** ppHacker)
{
    CHacker * pHacker = NULL;

    pHacker = new CHacker();
    if (NULL == pHacker) {
        return E_OUT_OF_MEMORY;
    }
    pHacker->AddRef();
    *ppHacker = pHacker;

    return NOERROR;
}

